#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdint.h>
#include <string.h>

uint32_t orig_code[] = {
  0x000004b8,      0x0001bb00,      0x34680000,      0x680a0d33,
0x35363738,      0x08bae189,      0xcd000000,      0x08c48380,
0x90909090,      0x90909090,      0x90909090,      0x90909090,
0x90909090,      0x90909090,      0x90909090,      0x90909090,
};

size_t code_size = sizeof(orig_code);

void mutate(uint32_t *code) {
    int i;
    
    // modify byte
    if (rand()%50==0)
    {
      //fprintf(stderr,"Modify byte\n");
      code[rand() % code_size] = rand() % 256;
    }
    
    // add byte
    if (rand()%80==0)
    {
      //fprintf(stderr,"Add byte\n");
      i = rand() % (code_size - 1);
      /* 0 1 2 3 4 5 6 7 8 9    size=10
       *             ^
       */
      memmove(code + i + 1, code + i, code_size - i);
      code[i] = rand();
    }

    // delete byte
    if (rand()%80==0 && code_size > 1)
    {
      //fprintf(stderr,"Delete byte\n");
      i = rand() % code_size;
      memmove(code + i, code + i + 1, code_size - i - 1);
    }
}

void copy_and_run(uint32_t *code) {
  uint8_t *mem;

  mem = (uint8_t *) mmap(0, code_size * 2, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  if ((void *) mem == MAP_FAILED)
    perror("mmap");
  memset(mem, 0x90909090, code_size * 2);
  mem[code_size * 2 - 1] = 0xc3;
  memcpy(mem, code, code_size);

  ( * (void (*)(void)) mem ) ();
  
  munmap (mem, code_size * 2);
}

void run() {
   mutate(orig_code);
   copy_and_run(orig_code);
}

void spawn() {
  if (fork() == 0) run();
  if (fork() == 0) run();
  spawn();
}

int main(int argc, char *argv[]) {
  int t;
  srand(time(0));
  //  spawn();
  for(t=0; t<100000; t++) run();
  
  return 0;
}
